# 构建使用蚁群算法解决CVRP问题时的点间距离矩阵
import math
import pandas as pd
import numpy as np


class Field:
    def __init__(self, length_field=60, width_field=50, turn_raduis=6, harvest_width=3):
        self.length_field = length_field
        self.width_field = width_field
        self.turn_raduis = turn_raduis
        self.harvest_width = harvest_width
        self.line_num = self.distribute_width()     # 行数n

# 计算转弯操作的最佳间隔行数
    def suitable_line(self):
        suit_line = (2 * self.turn_raduis) / self.harvest_width
        return suit_line

# 得出田块分行的行数n
    def distribute_width(self):
        n = int(self.length_field / self.harvest_width)
        return n

# 构建n X n的距离矩阵框架
    def distance_mtrix_raw(self):
        # n = self.distribute_width()
        raw_distance = np.zeros((self.line_num, self.line_num))
        for i in range(0, self.line_num):
            raw_distance[i][i] = np.inf
        return raw_distance

# 堆积点某一行与其他行的转弯距离计算
    def get_result_method(self, line_i=None, columns_j=None):
        # num_point为列，num_i为行索引
        d = float()
        x = abs(line_i - columns_j) / 2                        # abs（）  数值函数，取差的绝对值
        if 0 < x < self.suitable_line():
            try:
                d = (2 * self.turn_raduis) * (math.pi - 2 * (math.atan(
                    x * self.harvest_width / (
                                (4 * self.turn_raduis ** 2 - x ** 2 * self.harvest_width ** 2) ** 0.5))))
            except:
                d = np.inf
        elif x == self.suitable_line():
            d = math.pi * self.turn_raduis
        elif x > self.suitable_line():
            d = math.pi * self.turn_raduis + (x - self.suitable_line()) * self.harvest_width
        elif x == 0:
            d = np.inf
        return round(d, 1)

# 给初设的距离矩阵赋值
    def assignment_distance_matrix(self):
        data_matrix = self.distance_mtrix_raw()
        for i in range(0, self.line_num):
            if i % 2 == 1:                                               # 奇数行
                for j in range(0, self.line_num):                        # 列
                    if j % 2 == 0 and abs(j - i) == 1:
                        data_matrix[i, j] = self.width_field
                    elif j % 2 == 0 and abs(j - i) != 1:
                        data_matrix[i, j] = np.inf
                    else:
                        data_matrix[i, j] = self.get_result_method(i, j)
            else:                                                        # 偶数列
                for j in range(0, self.line_num):
                    if j % 2 == 1 and abs(j - i) == 1:
                        data_matrix[i, j] = self.width_field
                    elif j % 2 == 1 and abs(j - i) != 1:
                        data_matrix[i, j] = np.inf
                    else:
                        data_matrix[i, j] = self.get_result_method(i, j)
        # data_matrix[:, 0] = np.inf
        # data_matrix[0, :] = np.inf
        pd_data_matrix = pd.DataFrame(data_matrix)
        pd.set_option('max_colwidth', 200)
        pd.set_option('display.max_columns', None)
        pd.set_option('display.max_rows', None)
        pd.set_option('expand_frame_repr', False)
        print(pd_data_matrix)
        pd_data_matrix.to_csv('distance_matrix')


# 运行程序
distance_matrix = Field(60, 50, 6, 3)
distance_matrix.assignment_distance_matrix()
